﻿package modular {
	import flash.events.ErrorEvent;
	import flash.events.Event;
	
	import ch.sfug.data.Set;
	import ch.sfug.log.Logger;
	
	import modular.ModuleSet;
	import modular.events.ModuleEvent;
	import modular.module.Module;
	import modular.module.PreloaderModule;		

	/**
	 * @author mich
	 */
	public class ModuleSetLoader extends Module {

		private var oldSet:ModuleSet;
		private var activeSet:ModuleSet;
		protected var libLoader:LibraryLoader;

		public function ModuleSetLoader() {
			
			super();
			libLoader = new LibraryLoader();
			libLoader.addEventListener(Event.COMPLETE, createActiveModuleSet);
			
			addEventListener(ModuleEvent.INFO_CHANGED, onInfoChanged);
		}
		

		
		public function loadModuleSet( ms:ModuleSet ):void {
			
			oldSet = activeSet;
			activeSet = ms.clone();
			activeSet.loader = this;
			
			if( oldSet != null ) oldSet.transferEqualModules(activeSet);
			
			var libs:Set = activeSet.getLibrariesToLoad();
			if( libs.length > 0 ) {
				libLoader.loadLibraries(libs);
			} else {
				createActiveModuleSet();
			}
		}
		
		public function unload():void {
			if( activeSet != null ) {
				activeSet.hide();
				activeSet = null;
			}
		}

		
		
		
		private function createActiveModuleSet( event:Event = null ):void {
			try {
				
				if( oldSet != null ) {
					oldSet.hide();
					oldSet.destroy();
				}
				
				activeSet.createInstancesOn( this );
				activeSet.show();
				
				dispatchEvent(new ModuleEvent(ModuleEvent.ALL_MODULES_READY));
			} catch( e:Error ) {
				Logger.log(e.message, Modular.LOG_ERROR);
			}
		}


		private function createPreloader( event:Event = null ):void {
			try {
				var preloaderItem:ModuleSetItem = new ModuleSetItem(info.rawXML.preloader.Module[0] );
				preloaderItem.createInstanceOn( this );
				libLoader.preloader = PreloaderModule(preloaderItem.module);
				Logger.log("preloader: " + libLoader.preloader + " created.", Modular.LOG_INFO);
			} catch( e:Error ) {
				Logger.log(e.message, Modular.LOG_ERROR);
			}
			
			libLoader.addEventListener(Event.COMPLETE, createActiveModuleSet);
			libLoader.removeEventListener(Event.COMPLETE, createPreloader);
			
			loadAutoLoad();
		}

		
		public function getModuleByID( id:String ):Module {
			if( info != null && info.id == id ) {
				return this;
			} else {
				return ( activeSet != null ) ? activeSet.getModuleByID(id) : null;
			}
		}


		public function getModuleByClass( className:String ):Module {
			if( info != null && info.className == className ) {
				return this;
			} else {
				return ( activeSet != null ) ? activeSet.getModuleByClass(className) : null;
			}
		}

		
		public function parseXML( xml:XML ):void {
			
			if( xml.preloader.Module[0] != undefined ) {
				
				var preloaderItem:ModuleSetItem = new ModuleSetItem( xml.preloader.Module[0] );

				if( preloaderItem.getLibrary() != "" ) {
					var libs:Set = new Set();
					libs.add( preloaderItem.getLibrary() );
					libLoader.removeEventListener(Event.COMPLETE, createActiveModuleSet);
					libLoader.addEventListener(Event.COMPLETE, createPreloader);
					libLoader.loadLibraries(libs);
				} else {
					createPreloader();
				}
			} else {
				loadAutoLoad();
			}
		}


		private function loadAutoLoad():void {
			if( info.rawXML.autoload.ModuleSet[0] != undefined ) {
				loadModuleSet(new ModuleSet(info.rawXML.autoload.ModuleSet[0]));
			} else {
				Logger.log("No ModuleSet to autoload in: " + this, Modular.LOG_INFO);
			}
		}

		
		private function onAllModulesShown(event:ModuleEvent):void {
			info.parentLoader.removeEventListener(ModuleEvent.ALL_MODULES_READY, onAllModulesShown);
			parseXML(info.rawXML);
		}


		protected function onInfoChanged(event:ModuleEvent):void {
			info.parentLoader.addEventListener(ModuleEvent.ALL_MODULES_READY, onAllModulesShown);
			libLoader.preloader = preloader;
		}
		
		public function get preloader():PreloaderModule {
			if( libLoader.preloader == null ) {
				return info.parentLoader.preloader;
			} else {
				return libLoader.preloader;
			}
		}
	}
}
